#pragma once

#include <vector>
#include <cassert>

#include "util.hpp"

namespace iceLogs
{


#define _MAX_SIZE_ (1024 * 1024 * 10)
#define THRESHOLD_BUFFER_SIZE (1024 * 1024 * 10)
#define INCREMENT_BUFFER_SIZE (1024 * 1024 * 10)
class Buffer
{
    public:
        Buffer():_buffer(_MAX_SIZE_),_read_idx(0),_write_idx(0)
        {

        }

        //向缓冲区写入数据
        void push(const char* data, size_t len)
        {
            //固定缓冲区大小，不进行扩容
            //if(len > writeAbleSize()) return ;

            //动态内存空间，空间不够则进行扩容
            ensureEnoughSize(len);


            //将数据拷贝到缓冲区
            std::copy(data, data + len, &(_buffer[_write_idx]));

            moveWriter(len);
        }

        //返回可读数据位置的起始地址
        const char* begin()
        {
            return &_buffer[_read_idx];
        }

        //返回可读数据的长度
        size_t readAbleSize()
        {
            return (_write_idx - _read_idx);
        }

        //返回可写数据的长度
        size_t writeAbleSize()
        {
            //该接口仅被用于固定缓冲区大小时使用,对于扩容思想来说，缓冲区一直可以写入，不需要用到该接口
            return _buffer.size() - _write_idx;
        }

        //移动读指针
        void moveReader(size_t len)
        {
            assert(len <= readAbleSize());
            _read_idx += len;
        }


        //重置读写位置
        void reset()
        {
            _read_idx = 0;
            _write_idx = 0;
        }

        //交换缓冲区指针
        void swap(Buffer &buffer)
        {
            _buffer.swap(buffer._buffer);
            std::swap(_write_idx, buffer._write_idx);
            std::swap(_read_idx, buffer._read_idx);
        }

        //判断缓冲区是否为空
        bool empty()
        {
            return (_read_idx == _write_idx);
        }
    private:
        //对空间进行扩容
        void ensureEnoughSize(size_t len)
        {
            if(len < writeAbleSize()) return ;
            size_t new_size = 0;

            if (_buffer.size() < THRESHOLD_BUFFER_SIZE) // 小于阈值成倍增长
            {
                new_size = _buffer.size() * 2 + len;
            }
            else
            {
                new_size = _buffer.size() + INCREMENT_BUFFER_SIZE + len; // 大于阈值线性增长
            }

            _buffer.resize(new_size);
        }
        //移动写指针
        void moveWriter(size_t len)
        {
            assert(len + _write_idx < _buffer.size());
            _write_idx += len;
        }
    private:
        std::vector<char> _buffer;
        size_t _read_idx;
        size_t _write_idx;
};

}